package com.iot.ic.tcp.parse;


import com.iot.ic.tcp.DataType;
import com.iot.ic.tcp.model.MsgResponse;
import com.iot.ic.tcp.utils.ByteUtil;

import java.util.*;

/**
 * 数据封装成字节数组工具类
 *
 * @author xiuge 2016年10月17日下午5:18:04
 */
public class DataPackage {


    /**
     * 根据response中的数据解析发送的字节数组
     *
     * @param response
     * @return
     */
    public static byte[] packageSendData(MsgResponse response) {
        Byte header[] = response.getHeader();
        List<Byte> list = new LinkedList<Byte>(Arrays.asList(header));
        Byte[] dataType = ByteUtil.getBytes(response.getCmdCode());// 数据上传应答操作码
        for (int i = 0; i < dataType.length; i++) {
            list.add(dataType[i]);
        }
        Map<Byte, Map<Byte, Object>> sendMap = response.getSendMap();
        for (byte chKey : sendMap.keySet()) {// chkey代表通道码
            Map<Byte, Object> chMap = sendMap.get(chKey);
            if (chMap == null) {
                continue;
            }
            for (byte key : chMap.keySet()) {// key代表数据类型码
                LinkedList<Byte> data = new LinkedList<Byte>();
                data.add((byte) chKey);
                data.add((byte) key);
                switch (key) {
                    case DataType.Data.TIME:
                        Date date = (Date) chMap.get(key);
                        Byte[] dateBytes = ByteUtil.getBytes(date);
                        for (int i = 0; i < dateBytes.length; i++) {
                            data.addLast(dateBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;
                    case DataType.Data.UPLOAD_STEP:// 上传间隔
                        short step = (short) (int) chMap.get(key);
                        Byte[] stepBytes = ByteUtil.getBytes(step);
                        for (int i = 0; i < stepBytes.length; i++) {
                            data.addLast(stepBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;
                    case DataType.Data.IP_PORT:// ip和端口
                        String ipPort = (String) chMap.get(key);
                        Byte[] ipPortBytes = ByteUtil.getBytesByIpPort(ipPort);
                        for (int i = 0; i < ipPortBytes.length; i++) {
                            data.addLast(ipPortBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;
                    case DataType.Data.SETTING_FLAG:
                        data.add((byte) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;

                    case DataType.Data.ROM_FLAG:
                        data.add((byte) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;

                    case DataType.Data.ROM_DATA:
                        byte[] romData = (byte[]) chMap.get(key);
                        if (romData.length < 1024) {//数据包长度不足1024的用0xff补全
                            byte[] tmp = romData;
                            romData = new byte[1024];
                            romData = Arrays.copyOfRange(tmp, 0, romData.length);
                            Arrays.fill(romData, tmp.length, romData.length, (byte) 0xff);
                        }
                        for (int i = 0; i < 8; i++) {//把1024个字节分为八个数据发送，每个数据包含128个字节
                            LinkedList<Byte> romDataList = new LinkedList<Byte>();
                            romDataList.add((byte) chKey);
                            romDataList.add((byte) key);
                            byte[] romDataParam = Arrays.copyOfRange(romData, i * 128, (i + 1) * 128);
                            for (int j = 0; j < romDataParam.length; j++) {
                                romDataList.add(romDataParam[j]);
                            }
                            romDataList.addFirst((byte) romDataList.size());
                            list.addAll(romDataList);
                        }

                        break;

                    case DataType.Data.ROM_ORDER:
                        short romOrder = (short) (int) chMap.get(key);
                        Byte[] romOrderBytes = ByteUtil.getBytes(romOrder);
                        for (int i = 0; i < romOrderBytes.length; i++) {
                            data.addLast(romOrderBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;

                    case DataType.Data.ROM_NUM:
                        short romNum = (short) (int) chMap.get(key);
                        Byte[] romNumBytes = ByteUtil.getBytes(romNum);
                        for (int i = 0; i < romNumBytes.length; i++) {
                            data.addLast(romNumBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;

                    case DataType.Data.ROM_VERSION:
                        data.add((byte) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;

                    case DataType.Data.ALARM_ENABLE:
                        data.add((byte) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;

                    case DataType.Data.MAX_HUM:// 湿度上限
                        data.add((byte) (int) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;
                    case DataType.Data.MIN_HUM:// 湿度下限
                        data.add((byte) (int) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);
                        break;

                    case DataType.Data.MAX_TEM:// 温度上限
                        float maxTem = (float) chMap.get(key);
                        Byte[] maxTemBytes = ByteUtil.getBytes(maxTem);
                        for (int i = 0; i < maxTemBytes.length; i++) {
                            data.addLast(maxTemBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;
                    case DataType.Data.MIN_TEM:// 温度下限
                        float minTem = (float) chMap.get(key);
                        Byte[] minTemBytes = ByteUtil.getBytes(minTem);
                        for (int i = 0; i < minTemBytes.length; i++) {
                            data.addLast(minTemBytes[i]);
                        }
                        data.addFirst((byte) data.size());
                        list.addAll(data);

                        break;
                    case DataType.Data.TEM_ADJUST:// 温度下限
                        Float temAdjust = (Float) chMap.get(key);
                        if (temAdjust != null) {
                            byte tem = (byte) (temAdjust * 10);
                            data.add(tem);
                            data.addFirst((byte) data.size());
                            list.addAll(data);
                        }
                        break;
                    case DataType.Data.CHANNEL:// 通道数量
                        data.add((byte) (short) chMap.get(key));
                        data.addFirst((byte) data.size());
                        list.addAll(data);
                        break;
                    default:
                        break;
                }
            }
        }
        return null;
    }




    /**
     * 封装操作码
     *
     * @param cmdCode
     * @return
     */
    public static List<Byte> packageCmdCode(short cmdCode) {
        List<Byte> dataList = new ArrayList<>();
        byte dataType = (byte) (cmdCode / 256);
        byte cmdObject = (byte) (cmdCode % 256);
        dataList.add(dataType);
        dataList.add(cmdObject);
        return dataList;
    }

    /**
     * 添加数据包的公共部分（包头、长度、校验和、包尾）
     *
     * @param rspList
     * @return
     */
    public static byte[] packageData(LinkedList<Byte> rspList) {
        rspList.add(0, (byte) (rspList.size() + 3));
        byte vertifySum = 0;
        for (byte data : rspList) {
            vertifySum += data;
        }
        rspList.add(vertifySum);
        rspList.addLast((byte) 0xEE);
        rspList.addLast((byte) 0xee);
        rspList.addFirst((byte) 0xee);
        rspList.addFirst((byte) 0xff);
        Byte[] rspArrays = rspList.toArray(new Byte[rspList.size()]);
        byte[] rspArr = new byte[rspArrays.length];
        for (int i = 0; i < rspArrays.length; i++) {
            rspArr[i] = rspArrays[i];
        }
        return rspArr;
    }


    /**
     * 封装上传周期和报警时的上传周期
     *
     * @param step
     * @return
     */
    public static List<Byte> packageLoraStep(int step) {
        List<Byte> stepList = new ArrayList<>();
        int sec = step * 60;
        Byte first = (byte) (sec / 256);
        Byte second = (byte) (sec % 256);
        stepList.add(first);
        stepList.add(second);
        stepList.add((byte) 0);
        stepList.add((byte) 10);
        return stepList;
    }

}
